package com.netintech.project.system.service.impl;

import com.netintech.common.utils.hikSdk.FindFileResult;
import com.netintech.common.utils.hikSdk.HikSdkUtil;
import com.netintech.common.utils.hikSdk.LoginResult;
import com.netintech.core.web.domain.RequestResult;
import com.netintech.project.system.domain.NvrCamNotRecordPeriod;
import com.netintech.project.system.domain.bo.NvrInfo;
import com.netintech.project.system.domain.bo.NvrInfos;
import com.netintech.project.system.mapper.NvrCamNotRecordPeriodMapper;
import com.netintech.project.system.service.HikSdkService;
import com.sun.jna.NativeLong;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

/**
 * @author luda
 * @date 2021/3/3 15:12
 */
@Slf4j
@Service
public class HikSdkServiceImpl implements HikSdkService {
    @Autowired
    private NvrCamNotRecordPeriodMapper nvrCamNotRecordPeriodMapper;


    static DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");


    @Override
    public RequestResult queryRecordContinuity(String deviceIp, Integer port, String userName, String password,
                                               LocalDateTime startTime, LocalDateTime endTime, long channelNum, int useCard
    ) {
        List<FindFileResult> notRecordTime = new ArrayList<>();

        int startTimeYear = startTime.getYear();
        int startTimeMonthValue = startTime.getMonthValue();
        int startTimeDayOfMonth = startTime.getDayOfMonth();
        int startTimeHour = startTime.getHour();
        int startTimeMinute = startTime.getMinute();
        int startTimeSecond = startTime.getSecond();
        int endTimeYear = endTime.getYear();
        int endTimeMonthValue = endTime.getMonthValue();
        int endTimeDayOfMonth = endTime.getDayOfMonth();
        int endTimeHour = endTime.getHour();
        int endTimeMinute = endTime.getMinute();
        int endTimeSecond = endTime.getSecond();


        if (!HikSdkUtil.initSdk()) {
            log.error("SDK初始化失败！");
            return RequestResult.error("SDK初始化失败！");
        }
//        todo userId>-1，即注册成功后
        LoginResult loginResult = HikSdkUtil.login(deviceIp, port, userName, password);
        if (!loginResult.getSuccess()) {
            log.error("注册设备失败！");
            return RequestResult.error("注册设备失败！");
        }
        NativeLong lUserID = loginResult.getLUserID();
        List<FindFileResult> findFileResults = HikSdkUtil.findFile(lUserID, startTimeYear, startTimeMonthValue, startTimeDayOfMonth, startTimeHour, startTimeMinute, startTimeSecond,
                endTimeYear, endTimeMonthValue, endTimeDayOfMonth, endTimeHour, endTimeMinute, endTimeSecond, channelNum, useCard);

        if (CollectionUtils.isEmpty(findFileResults)) {
            return RequestResult.error("未查询到录像！");
        }

        getNotRecordPeriod(startTime, endTime, notRecordTime, findFileResults);

        HikSdkUtil.logout(lUserID);
        HikSdkUtil.cleanUp();
        return RequestResult.success(notRecordTime);
    }

    @Override
    public List<NvrCamNotRecordPeriod> queryRecordContinuityBatch(NvrInfos nvrInfos, LocalDateTime startTime, LocalDateTime endTime) {
        List<NvrCamNotRecordPeriod> nvrCamNotRecordPeriods = new ArrayList<>();
        final int useCard = 0;
        List<NvrInfo> list = nvrInfos.getList();
        if (!HikSdkUtil.initSdk()) {
            log.error("SDK初始化失败！");
            return nvrCamNotRecordPeriods;
        }

        int startTimeYear = startTime.getYear();
        int startTimeMonthValue = startTime.getMonthValue();
        int startTimeDayOfMonth = startTime.getDayOfMonth();
        int startTimeHour = startTime.getHour();
        int startTimeMinute = startTime.getMinute();
        int startTimeSecond = startTime.getSecond();
        int endTimeYear = endTime.getYear();
        int endTimeMonthValue = endTime.getMonthValue();
        int endTimeDayOfMonth = endTime.getDayOfMonth();
        int endTimeHour = endTime.getHour();
        int endTimeMinute = endTime.getMinute();
        int endTimeSecond = endTime.getSecond();

        for (NvrInfo nvrInfo : list) {
            LocalDateTime now = LocalDateTime.now();
            LoginResult loginResult = HikSdkUtil.login(nvrInfo.getIp(), nvrInfo.getPort(), nvrInfo.getUserName(), nvrInfo.getPassword());
            if (!loginResult.getSuccess()) {
                log.error("注册设备失败！", nvrInfo);
                continue;
            }
            NativeLong lUserID = loginResult.getLUserID();
            List<Integer> camChannelNumsByNvr = HikSdkUtil.getCamChannelNumsByNvr(lUserID, loginResult.getM_strDeviceInfo());
            if (CollectionUtils.isEmpty(camChannelNumsByNvr)) {
                continue;
            }
            for (Integer channelNum : camChannelNumsByNvr) {
                List<FindFileResult> findFileResults = HikSdkUtil.findFile(lUserID, startTimeYear, startTimeMonthValue, startTimeDayOfMonth, startTimeHour, startTimeMinute, startTimeSecond,
                        endTimeYear, endTimeMonthValue, endTimeDayOfMonth, endTimeHour, endTimeMinute, endTimeSecond, channelNum, useCard);
                List<FindFileResult> notRecordTime = new ArrayList<>();
                getNotRecordPeriod(startTime, endTime, notRecordTime, findFileResults);
                if (!CollectionUtils.isEmpty(notRecordTime)) {
                    for (FindFileResult findFileResult : notRecordTime) {
                        nvrCamNotRecordPeriods.add(NvrCamNotRecordPeriod.builder()
                                .nvrIp(nvrInfo.getIp())
                                .startTime(LocalDateTime.parse(findFileResult.getStartTime(), dateTimeFormatter))
                                .endTime(LocalDateTime.parse(findFileResult.getEndTime(), dateTimeFormatter))
                                .channel(channelNum)
                                .addTime(now)
                                .build());
                    }
                }
            }
            HikSdkUtil.logout(lUserID);
            HikSdkUtil.cleanUp();
        }
        return nvrCamNotRecordPeriods;
    }

    @Override
    public void insertBatch(List<NvrCamNotRecordPeriod> nvrCamNotRecordPeriods) {
        nvrCamNotRecordPeriodMapper.insertSelectiveBatch(nvrCamNotRecordPeriods);
    }

    /**
     * 根据录像时间段集合判断开始时间和结束时间内是否有未录像内容
     *
     * @param startTime
     * @param endTime
     * @param notRecordTime
     * @param findFileResults
     */
    private void getNotRecordPeriod(LocalDateTime startTime, LocalDateTime endTime, List<FindFileResult> notRecordTime, List<FindFileResult> findFileResults) {
        FindFileResult findFileResult01 = findFileResults.get(0);
        String startTime01 = findFileResult01.getStartTime();
        LocalDateTime localDateTime = LocalDateTime.parse(startTime01, dateTimeFormatter);
        if (startTime.isBefore(localDateTime)) {
            notRecordTime.add(FindFileResult.builder()
                    .startTime(dateTimeFormatter.format(startTime))
                    .endTime(startTime01)
                    .build());
        }
        for (int j = 0; j < findFileResults.size() - 1; j++) {
            FindFileResult findFileResult1 = findFileResults.get(j);
            FindFileResult findFileResult2 = findFileResults.get(j + 1);
            String endTime1 = findFileResult1.getEndTime();
            String startTime2 = findFileResult2.getStartTime();
            if (LocalDateTime.parse(endTime1, dateTimeFormatter).isBefore(LocalDateTime.parse(startTime2, dateTimeFormatter))) {
                notRecordTime.add(FindFileResult.builder()
                        .startTime(endTime1)
                        .endTime(startTime2)
                        .build());
            }
        }

        FindFileResult findFileResultLast = findFileResults.get(findFileResults.size() - 1);
        String endTimeLast = findFileResultLast.getEndTime();
        LocalDateTime localDateTimeLast = LocalDateTime.parse(endTimeLast, dateTimeFormatter);
        if (endTime.isAfter(localDateTimeLast)) {
            notRecordTime.add(FindFileResult.builder()
                    .startTime(endTimeLast)
                    .endTime(dateTimeFormatter.format(endTime))
                    .build());
        }
    }

}
